from concepts import *

from .person import Person

import random


class Seeker(Person):
    target  = Attribute(writable = True, setter = lambda self, target: self.move_to(target))
    path    = Attribute(writable = True)
    
    @property
    def is_homebound(self):
        return self.home is not None and self.target == self.home
    
    @property
    def has_path(self):
        return self.path is not None
    
    @property
    def target_area(self):
        if isinstance(self.target, Position):
            return self.target.area
        else:
            return self.target.area.grown_by(1)
    
    @property
    def has_arrived(self):
        if self.target is None or not self.exists:
            return False
        
        if hasattr(self.target, 'exists') and not self.target.exists:
            return False
        
        if hasattr(self.target, 'area'):
            return self.position in self.target_area
        else:
            return self.position == self.target
    
    def waiting(self):
        if self.has_path:
            self.follow_path()
        else:
            self.on_idle()
    
    def follow_path(self):
        try:
            self.step = self.path.next()
            
            if not self.can_pass(self.city.map.at(self.step)) and False: # FIXME
                self.step = None
                self.path = self.path_to(self.target)
                
                if self.path is None:
                    self.end_of_path()
        except StopIteration:
            self.path = None
            self.end_of_path()
    
    def end_of_path(self):
        if self.has_arrived:
            self.on_arrival()
            
            if self.is_homebound:
                self.on_arrival_home()
            else:
                self.on_arrival_away()
        else:
            self.on_dead_end()
    
    def move_to(self, target):
        self._target = target
        
        if target is not None:
            self.path = self.path_to(target)
            
            if self.path is None:
                self.end_of_path()
        else:
            self.path = None
    
    def move_to_random(self, targets):
        if targets:
            self.move_to(random.choice(targets))
    
    def move_home(self):
        self.move_to(self.home)
    
    def on_arrival(self):
        pass
    
    def on_arrival_home(self):
        pass
    
    def on_arrival_away(self):
        pass
    
    def on_dead_end(self):
        pass
    
    def on_idle(self):
        pass
